from django import template
import copy
import json
from simpleui.templatetags.simpletags import *
from simpleui.templatetags.simpletags import register


# 核心改进：处理多层级空菜单（支持无限层级）
def get_filtered_menus(menus, user_permissions):
    def filter_menu(menu, permissions):
        # 1. 先递归处理所有子菜单（从最深层开始清理）
        if 'models' in menu:
            # 递归过滤每个子菜单
            for sub_menu in menu['models']:
                filter_menu(sub_menu, permissions)

            # 2. 过滤当前层级的子菜单：保留有权限且非空的子菜单
            # （注意：此时子菜单已经过递归处理，空菜单已被标记）
            valid_children = []
            for sub_menu in menu['models']:
                # 子菜单本身有权限，且：
                # - 要么没有子菜单（本身是叶子节点）
                # - 要么有子菜单且不为空（经过递归后仍有有效子菜单）
                if ('permission' not in sub_menu or sub_menu['permission'] in permissions) and \
                        ('models' not in sub_menu or len(sub_menu['models']) > 0):
                    valid_children.append(sub_menu)

            # 3. 更新当前菜单的子菜单列表
            menu['models'] = valid_children

    # 第一步：过滤顶层菜单（基础权限检查）
    menu_configs = [
        menu for menu in menus
        if 'permission' not in menu or menu['permission'] in user_permissions
    ]

    # 第二步：递归过滤所有层级的子菜单（从内到外清理空菜单）
    for menu in menu_configs:
        filter_menu(menu, permissions=user_permissions)

    # 第三步：过滤顶层空菜单（所有子菜单都被清理的顶层菜单）
    final_menus = []
    for menu in menu_configs:
        # 保留：
        # - 没有子菜单的顶层菜单（本身是叶子节点）
        # - 有子菜单且不为空的顶层菜单
        if 'models' not in menu or len(menu['models']) > 0:
            final_menus.append(menu)

    return final_menus


# 以下是复用的 menus 标签代码（保持不变，仅依赖上面的 get_filtered_menus）
@register.simple_tag(takes_context=True)
def menus(context, _get_config=None):
    data = []
    if not _get_config:
        _get_config = get_config
    config = _get_config('SIMPLEUI_CONFIG')
    if not config:
        config = {}
    else:
        config = copy.deepcopy(config)
    app_list = context.get('app_list')
    for app in app_list:
        _models = [
            {
                'name': m.get('name'),
                'icon': get_icon(m.get('object_name'), unicode_to_str(m.get('name'))),
                'url': m.get('admin_url'),
                'addUrl': m.get('add_url'),
                'breadcrumbs': [{
                    'name': app.get('name'),
                    'icon': get_icon(app.get('app_label'), app.get('name'))
                }, {
                    'name': m.get('name'),
                    'icon': get_icon(m.get('object_name'), unicode_to_str(m.get('name')))
                }]
            }
            for m in app.get('models')
        ] if app.get('models') else []
        module = {
            'name': app.get('name'),
            'icon': get_icon(app.get('app_label'), app.get('name')),
            'models': _models
        }
        data.append(module)
    if has_permission_in_config(config):
        config["menus"] = get_filtered_menus(config["menus"], context.request.user.get_all_permissions())
    if config and 'menus' in config:
        if config.get('system_keep', None):
            temp = config.get('menus')
            for i in temp:
                if 'models' in i:
                    for k in i.get('models'):
                        k['breadcrumbs'] = [{
                            'name': i.get('name'),
                            'icon': i.get('icon')
                        }, {
                            'name': k.get('name'),
                            'icon': k.get('icon')
                        }]
                else:
                    i['breadcrumbs'] = [{
                        'name': i.get('name'),
                        'icon': i.get('icon')
                    }]
                data.append(i)
        else:
            data = config.get('menus')
    if config.get('menu_display') is not None:
        display_data = list()
        for _app in data:
            if _app['name'] not in config.get('menu_display'):
                continue
            _app['_weight'] = config.get('menu_display').index(_app['name'])
            display_data.append(_app)
        display_data.sort(key=lambda x: x['_weight'])
        data = display_data
    eid = 1000
    handler_eid(data, eid)
    menus_string = json.dumps(data, cls=LazyEncoder)
    if not isinstance(context, dict) and context.request:
        context.request.session['_menus'] = menus_string
    return '<script type="text/javascript">var menus={}</script>'.format(menus_string)

    return filtered_menus


# 重写 menus 标签（保持标签名与原标签一致）
@register.simple_tag(takes_context=True)
def menus(context, _get_config=None):
    # 以下代码复制自 simpleui 原 menus 标签，仅替换 get_filtered_menus 调用
    data = []

    if not _get_config:
        _get_config = get_config

    config = _get_config('SIMPLEUI_CONFIG')
    if not config:
        config = {}
    else:
        config = copy.deepcopy(config)

    app_list = context.get('app_list')
    for app in app_list:
        _models = [
            {
                'name': m.get('name'),
                'icon': get_icon(m.get('object_name'), unicode_to_str(m.get('name'))),
                'url': m.get('admin_url'),
                'addUrl': m.get('add_url'),
                'breadcrumbs': [{
                    'name': app.get('name'),
                    'icon': get_icon(app.get('app_label'), app.get('name'))
                }, {
                    'name': m.get('name'),
                    'icon': get_icon(m.get('object_name'), unicode_to_str(m.get('name')))
                }]
            }
            for m in app.get('models')
        ] if app.get('models') else []

        module = {
            'name': app.get('name'),
            'icon': get_icon(app.get('app_label'), app.get('name')),
            'models': _models
        }
        data.append(module)

    # 关键：使用自定义的 get_filtered_menus 函数
    if has_permission_in_config(config):
        config["menus"] = get_filtered_menus(config["menus"], context.request.user.get_all_permissions())

    if config and 'menus' in config:
        if config.get('system_keep', None):
            temp = config.get('menus')
            for i in temp:
                if 'models' in i:
                    for k in i.get('models'):
                        k['breadcrumbs'] = [{
                            'name': i.get('name'),
                            'icon': i.get('icon')
                        }, {
                            'name': k.get('name'),
                            'icon': k.get('icon')
                        }]
                else:
                    i['breadcrumbs'] = [{
                        'name': i.get('name'),
                        'icon': i.get('icon')
                    }]
                data.append(i)
        else:
            data = config.get('menus')

    if config.get('menu_display') is not None:
        display_data = list()
        for _app in data:
            if _app['name'] not in config.get('menu_display'):
                continue
            _app['_weight'] = config.get('menu_display').index(_app['name'])
            display_data.append(_app)
        display_data.sort(key=lambda x: x['_weight'])
        data = display_data

    eid = 1000
    handler_eid(data, eid)
    menus_string = json.dumps(data, cls=LazyEncoder)

    if not isinstance(context, dict) and context.request:
        context.request.session['_menus'] = menus_string

    return '<script type="text/javascript">var menus={}</script>'.format(menus_string)
